package com.exceptions;

import java.util.Date;

public class BaseException extends Exception{
	 /**
	 * 
	 */
	private static final long serialVersionUID = 983730082L;
	/**
     * <p>
     * Storage container for the extra information attached to this exception.
     * </p>
     * <p>
     * This is initialized on construction, either to a new
     * <code>ExceptionData()</code> or to a given exception data parameter.
     * Afterwards it will be non-null and immutable though its internal values
     * may change.
     * </p>
     * <p>
     * It is then used within any set/get method, the call is delegated to this
     * member which updates its state.
     * </p>
     *
     * @since 2.0
     */
    private final ExceptionData data;

    /**
     * <p>
     * Default no-argument constructor.
     * </p>
     * <p>
     * This also initializes the internal data member to a new <code>ExceptionData()</code>
     * instance.
     * </p>
     * <p>
     * <b>Changes to v2.0: </b> The internal data member is initialized to a new
     * <code>ExceptionData()</code>.
     * </p>
     *
     * @since 1.0
     */
    public BaseException() {
        this(new ExceptionData());
    }

    /**
     * <p>
     * Message-only constructor, initializes a new exception with the given
     * <code>message</code>.
     * </p>
     * <p>
     * This also initializes the internal data member to a new <code>ExceptionData()</code>
     * instance.
     * </p>
     * <p>
     * <b>Changes to v2.0: </b> The internal data member is initialized to a new
     * <code>ExceptionData()</code>.
     * </p>
     *
     * @param message Useful message containing a description of why the
     *            exception was thrown - may be null.
     * @since 1.0
     */
    public BaseException(String message) {
        this(message, new ExceptionData());
    }

    /**
     * <p>
     * Cause-only constructor, initializes a new exception with the given
     * <code>cause</code>.
     * </p>
     * <p>
     * This also initializes the internal data member to a new <code>ExceptionData()</code>
     * instance.
     * </p>
     * <p>
     * <b>Changes to v2.0: </b> The internal data member is initialized to a new
     * <code>ExceptionData()</code>.
     * </p>
     *
     * @param cause The initial throwable reason which triggered this exception
     *            to be thrown - may be null.
     * @since 1.0
     */
    public BaseException(Throwable cause) {
        this(cause, new ExceptionData());
    }

    /**
     * <p>
     * Constructor which takes a <code>message</code> and a <code>cause</code>
     * detailing why the exception occurs.
     * </p>
     * <p>
     * This also initializes the internal data member to a new <code>ExceptionData()</code>
     * instance.
     * </p>
     * <p>
     * <b>Changes to v2.0: </b> The internal data member is initialized to a new
     * <code>ExceptionData()</code>.
     * </p>
     *
     * @param message Useful message containing a description of why the
     *            exception was thrown - may be null.
     * @param cause The initial throwable reason which triggered this exception
     *            to be thrown - may be null.
     * @since 1.0
     */
    public BaseException(String message, Throwable cause) {
        this(message, cause, new ExceptionData());
    }

    /**
     * <p>
     * Constructor that takes only the additional <code>data</code> to attach
     * to the exception.
     * </p>
     * <p>
     * This sets the data member to the given parameter.If the data parameter is
     * null, a new <code>ExceptionData()</code> is used instead.
     * </p>
     *
     * @param data The additional data to attach to the exception - if this is
     *            null, a new <code>ExceptionData()</code> is used instead.
     * @since 2.0
     */
    public BaseException(ExceptionData data) {
        super();
        // set data field to data parameter if it is not null
        // a new ExceptionData() is used if data parameter is null
        this.data = (data != null) ? data : new ExceptionData();

    }

    /**
     * <p>
     * Constructs the exception taking both a <code>message</code> and the
     * additional <code>data</code> to attach to the exception.
     * </p>
     * <p>
     * This sets the data member to the given parameter.If the data parameter is
     * null, a new <code>ExceptionData()</code> is used instead.
     * </p>
     *
     * @param message Useful message containing a description of why the
     *            exception was thrown - may be null.
     * @param data The additional data to attach to the exception - if this is
     *            null, a new <code>ExceptionData()</code> is used instead.
     * @since 2.0
     */
    public BaseException(String message, ExceptionData data) {
        super(message);
        // set data field to data parameter if it is not null
        // a new ExceptionData() is used if data parameter is null
        this.data = (data != null) ? data : new ExceptionData();

    }

    /**
     * <p>
     * Constructs the exception taking an original <code>cause</code>, as
     * well as the additional <code>data</code> to attach to the exception.
     * </p>
     * <p>
     * This sets the data member to the given parameter.If the data parameter is
     * null, a new <code>ExceptionData()</code> is used instead.
     * </p>
     *
     * @param cause The initial throwable reason which triggered this exception
     *            to be thrown - may be null.
     * @param data The additional data to attach to the exception - if this is
     *            null, a new <code>ExceptionData()</code> is used instead.
     * @since 2.0
     */
    public BaseException(Throwable cause, ExceptionData data) {
        super(cause);
        // set data field to data parameter if it is not null
        // a new ExceptionData() is used if data parameter is null
        this.data = (data != null) ? data : new ExceptionData();

    }

    /**
     * <p>
     * Constructs the exception taking both a <code>message</code> and a
     * <code>cause</code>, as well as the additional <code>data</code> to
     * attach to the exception.
     * </p>
     * <p>
     * This sets the data member to the given parameter.If the data parameter is
     * null, a new <code>ExceptionData()</code> is used instead.
     * </p>
     *
     * @param message Useful message containing a description of why the
     *            exception was thrown - may be null.
     * @param cause The initial throwable reason which triggered this exception
     *            to be thrown - may be null.
     * @param data The additional data to attach to the exception - if this is
     *            null, a new <code>ExceptionData()</code> is used instead.
     * @since 2.0
     */
    public BaseException(String message, Throwable cause, ExceptionData data) {
        super(message, cause);

        // set data field to data parameter if it is not null
        // a new ExceptionData() is used if data parameter is null
        this.data = (data != null) ? data : new ExceptionData();
    }

    /**
     * <p>
     * Returns a piece of information attached to the exception with the given
     * <code>key</code>.
     * </p>
     *
     * @param key The key used to locate the information being received - may be
     *            null.
     * @return The value associated to the key, or null if not found.
     * @since 2.0
     */
    public Object getInformation(Object key) {
        // delegates to the data member to get the information related to the
        // key
        return data.getInformation(key);
    }

    /**
     * <p>
     * Sets a certain <code>value</code> for the exception, given a
     * <code>key</code> to identify it.
     * </p>
     *
     * @param key The key whose value is to be set - may be null.
     * @param value The value to associate to the key - may be null.
     * @since 2.0
     */
    public void setInformation(Object key, Object value) {
        // delegates to the data member to add a (key,value) pair
        data.setInformation(key, value);
    }

    /**
     * <p>
     * Returns whether the exception instance has been logged.
     * </p>
     *
     * @return The value of the stored logged flag, indicating whether the
     *         exception has been logged.
     * @since 2.0
     */
    public boolean isLogged() {
        // delegates to the data member to get the logged flag
        return data.isLogged();
    }

    /**
     * <p>
     * Sets the logged flag on the exception to the parameter.
     * </p>
     *
     * @param logged whether or not the exception has been logged
     * @since 2.0
     */
    public void setLogged(boolean logged) {
        // delegates to the data member to set the logged flag
        data.setLogged(logged);
    }

    /**
     * <p>
     * Returns the application code attached to the exception.
     * </p>
     *
     * @return The application code attached to the exception - this may be
     *         null.
     * @since 2.0
     */
    public String getApplicationCode() {
        // delegates to the data member to get the application code
        return data.getApplicationCode();
    }

    /**
     * <p>
     * Returns the module code attached to the exception.
     * </p>
     *
     * @return The module code attached to the exception - this may be null.
     * @since 2.0
     */
    public String getModuleCode() {
        // delegates to the data member to get the module code
        return data.getModuleCode();
    }

    /**
     * <p>
     * Returns the error code attached to the exception.
     * </p>
     *
     * @return The error code attached to the exception - this may be null.
     * @since 2.0
     */
    public String getErrorCode() {
        // delegates to the data member to get the error code
        return data.getErrorCode();
    }

    /**
     * <p>
     * Returns the <code>Date</code> instance corresponding to the date and
     * time when the exception was initialized - will not be null.
     * </p>
     *
     * @return the date and time when the exception was first created.
     * @since 2.0
     */
    public Date getCreationDate() {
        // delegates to the data member to get the date and time
        return data.getCreationDate();
    }

    /**
     * <p>
     * Returns the name of the thread which the exception was raised in - will
     * not be null.
     * </p>
     *
     * @return the name of the thread throwing the exception.
     * @since 2.0
     */
    public String getThreadName() {
        // delegates to the data member to get the thread name
        return data.getThreadName();
    }
}
